import logging
import os
import json
import time
import requests
from typing import Dict, List, Any, Optional
from .base_processor import BaseProcessor

class ClassificationProcessor(BaseProcessor):
    """
    分类处理器，负责对资讯进行分类标记
    """
    
    def __init__(self, config: Dict[str, Any] = None):
        """
        初始化分类处理器
        
        Args:
            config: 处理器配置
        """
        super().__init__(config)
        # LLM配置，复用摘要处理器的LLM配置
        self.llm_config = self.config.get('llm', {})
        self.default_provider = self.llm_config.get('default', 'deepseek')
        
        # 加载环境变量中的API密钥
        self.api_keys = {}
        for provider, provider_config in self.llm_config.get('providers', {}).items():
            api_key_var = provider_config.get('api_key', '')
            if api_key_var.startswith('${') and api_key_var.endswith('}'):
                env_var = api_key_var[2:-1]
                api_key = os.environ.get(env_var)
                if api_key:
                    self.api_keys[provider] = api_key
                else:
                    self.logger.warning(f"API key for {provider} not found in environment variable {env_var}")
        
        # 定义分类体系
        self.categories = [
            "大语言模型", "多模态", "生成式AI", "AI框架", "AI工具", "AI应用",
            "AI研究", "AI伦理", "AI监管", "AI创业", "AI产业", "AI开源",
            "AI芯片", "算法进展", "技术评测", "行业动态"
        ]
        
        self.tech_level_categories = [
            "前沿研究", "技术创新", "产品应用", "商业动态", "行业趋势"
        ]
        
        self.target_audience = [
            "研究人员", "工程师", "产品经理", "商业决策者", "普通用户", "投资者"
        ]
    
    def process(self, data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        处理数据，对每项进行分类
        
        Args:
            data: 要处理的数据列表
            
        Returns:
            处理后的数据列表
        """
        # 过滤无效数据
        valid_data = self.filter_invalid(data)
        
        processed_data = []
        for item in valid_data:
            try:
                # 如果已有分类且不为空，跳过
                if item.get('categories') and isinstance(item.get('categories'), list) and len(item.get('categories', [])) > 0:
                    processed_data.append(item)
                    continue
                
                # 获取标题和内容
                title = item.get('title', '')
                content = item.get('abstract', '') or item.get('content', '') or item.get('summary', '')
                
                # 获取已有关键词
                existing_keywords = item.get('keywords', [])
                keywords_text = ", ".join(existing_keywords) if existing_keywords else ""
                
                # 进行分类
                categories = self._classify_content(title, content, keywords_text)
                item.update(categories)
                
                # 添加元数据
                self.add_metadata(item)
                processed_data.append(item)
                
                # 添加延迟，避免API请求过于频繁
                time.sleep(0.5)
                
            except Exception as e:
                self.logger.error(f"Error classifying item {item.get('id', 'unknown')}: {str(e)}")
                # 添加原始项目，确保数据不丢失
                processed_data.append(item)
        
        self.logger.info(f"Classified {len(processed_data)} items")
        return processed_data
    
    def _classify_content(self, title: str, content: str, keywords: str = "") -> Dict[str, Any]:
        """
        对内容进行分类
        
        Args:
            title: 标题
            content: 内容
            keywords: 已有关键词，逗号分隔
            
        Returns:
            分类结果
        """
        # 构造提示词
        prompt = f"""请对以下AI技术相关内容进行分类标记。请仅返回JSON格式的分类结果，不要有任何其他文字。

标题: {title}

内容摘要: {content[:500]}

已有关键词: {keywords}

请从以下几个维度进行分类，并按以下JSON格式返回结果：

1. 主题分类(topic_categories)：从以下类别中选择1-3个最匹配的：
   {", ".join(self.categories)}

2. 技术层次(tech_level)：从以下层次中选择1个最匹配的：
   {", ".join(self.tech_level_categories)}

3. 目标受众(target_audience)：从以下受众中选择1-2个最匹配的：
   {", ".join(self.target_audience)}

4. 热度评估(popularity_score)：根据内容的新颖性、影响力和关注度，给1-5的分数，5分为最高

5. 细分领域(specific_domain)：简要说明该内容属于哪个细分技术领域(15字以内)

结果示例：
```json
{{
  "topic_categories": ["大语言模型", "AI研究"],
  "tech_level": "前沿研究",
  "target_audience": ["研究人员", "工程师"],
  "popularity_score": 4,
  "specific_domain": "文本生成模型"
}}
```

只返回JSON格式结果，不要有其他文字："""
        
        # 调用LLM API
        classification_text = self._call_llm_api(prompt)
        
        if not classification_text:
            # 如果API调用失败，返回基本分类
            return {
                "topic_categories": ["AI应用"],
                "tech_level": "技术创新",
                "target_audience": ["工程师"],
                "popularity_score": 3,
                "specific_domain": "人工智能"
            }
        
        # 解析JSON结果
        try:
            # 提取JSON部分
            json_match = classification_text.strip()
            if "```json" in json_match:
                json_match = json_match.split("```json")[1].split("```")[0].strip()
            elif "```" in json_match:
                json_match = json_match.split("```")[1].split("```")[0].strip()
                
            classification = json.loads(json_match)
            
            # 验证结果格式
            if not isinstance(classification.get("topic_categories", []), list):
                classification["topic_categories"] = [classification.get("topic_categories", "AI应用")]
                
            if not isinstance(classification.get("target_audience", []), list):
                classification["target_audience"] = [classification.get("target_audience", "工程师")]
                
            # 规范化热度分数
            popularity_score = classification.get("popularity_score", 3)
            try:
                popularity_score = int(popularity_score)
                if popularity_score < 1:
                    popularity_score = 1
                elif popularity_score > 5:
                    popularity_score = 5
            except:
                popularity_score = 3
            classification["popularity_score"] = popularity_score
            
            return classification
            
        except Exception as e:
            self.logger.error(f"Error parsing classification result: {str(e)}, text: {classification_text}")
            # 返回基本分类
            return {
                "topic_categories": ["AI应用"],
                "tech_level": "技术创新",
                "target_audience": ["工程师"],
                "popularity_score": 3,
                "specific_domain": "人工智能"
            }
    
    def _call_llm_api(self, prompt: str, provider: Optional[str] = None) -> Optional[str]:
        """
        调用LLM API
        
        Args:
            prompt: 提示词
            provider: LLM提供商，为None则使用默认提供商
            
        Returns:
            API返回的文本，失败返回None
        """
        provider = provider or self.default_provider
        
        if provider not in self.api_keys:
            self.logger.error(f"API key not found for provider {provider}")
            return None
        
        api_key = self.api_keys[provider]
        provider_config = self.llm_config.get('providers', {}).get(provider, {})
        base_url = provider_config.get('base_url', '')
        model = provider_config.get('model', '')
        
        if not base_url or not model:
            self.logger.error(f"Invalid configuration for provider {provider}")
            return None
        
        try:
            headers = {
                "Content-Type": "application/json",
                "Authorization": f"Bearer {api_key}"
            }
            
            payload = {
                "model": model,
                "messages": [
                    {"role": "system", "content": "你是一个专业的AI技术内容分类助手。请提供准确的分类结果，只返回JSON格式的数据，不要有任何额外的解释或说明。"},
                    {"role": "user", "content": prompt}
                ],
                "temperature": 0.2,
                "max_tokens": 500
            }
            
            response = requests.post(
                f"{base_url}/chat/completions", 
                headers=headers, 
                json=payload,
                timeout=30
            )
            
            if response.status_code == 200:
                result = response.json()
                # 解析不同提供商的响应
                if provider == "openai":
                    return result.get("choices", [{}])[0].get("message", {}).get("content", "")
                elif provider == "deepseek":
                    return result.get("choices", [{}])[0].get("message", {}).get("content", "")
                else:
                    return result.get("choices", [{}])[0].get("message", {}).get("content", "")
            else:
                self.logger.error(f"API error: {response.status_code} {response.text}")
                return None
        
        except Exception as e:
            self.logger.error(f"Error calling LLM API: {str(e)}")
            return None 